import axios from "axios";
import { ElNotification,ElMessage } from "element-plus";
import { getToken } from "../utils/auth";
import { Method, RequestFunctionParams } from "yapi-to-typescript";
import { generateUUID } from "@dcb/utils";

const useDevUrl = true;

// const corsProxyUrl = 'https://dcb-cors.duocairen.com/';
const corsProxyUrl = "";

export default function request<TResponseData>(
  payload: RequestFunctionParams,
  options: {
    timeout?: number;
    ignoreError?: boolean;
    responseIsFile?: boolean;
    onCancel?: () => any;
  } = {}
): Promise<TResponseData> {
  options.timeout =
    options.timeout == null
      ? payload.hasFileData
        ? // 文件上传类接口 20 分钟
        20 * 60 * 1000
        : // 其他接口 1 分钟
        1 * 60 * 1000
      : options.timeout;
  options.ignoreError =
    options.ignoreError == null ? false : options.ignoreError;
  options.responseIsFile =
    options.responseIsFile == null ? false : options.responseIsFile;
  return new Promise<TResponseData>((resolve, reject) => {
    // 基本地址
    // @ts-ignore
    const baseUrl = useDevUrl
      ? `${corsProxyUrl}${import.meta.env.VITE_APP_BASE_API || payload.devUrl}`
      : "";
    // 请求地址
    const url = `${baseUrl}${payload.path}`;

    // 重试函数
    const retry = () => request(payload, options).then(resolve as any, reject);

    // 具体请求逻辑
    return axios({
      url: url,
      method: payload.method,
      timeout: options.timeout,
      validateStatus: () => true,
      headers: {
        Authorization: `Bearer ${getToken()}`,
      },
      ...(payload.method === Method.POST
        ? {
          data: payload.hasFileData ? payload.getFormData() : payload.data,
        }
        : {}),
      ...(options.responseIsFile
        ? {
          responseType: "blob",
        }
        : {}),
    })
      .then((res) => {
        if (res.status !== 200) {
          notify({
            apiName: payload.extraInfo.name,
            apiUrl: payload.extraInfo.url,
            apiAuthor: payload.extraInfo.author,
            url: url,
            data: payload.data,
            message:
              (res.data && JSON.stringify(res.data)) ||
              res.statusText ||
              res.status,
            onRetry: retry,
            onCancel: options.onCancel,
            onClose: () => reject(res),
          });
        } else if (
          res.data &&
          typeof res.data === "object" &&
          (("status" in res.data && res.data.status !== 200) ||
            ("code" in res.data && res.data.code !== 200))
        ) {
          if (res.data.status === 401 || res.data.code === 401) {
            location.href = location.href.split("#")[0];
            return;
          }
          ElMessage.error(res.data.msg || res.data.message || "未知错误");
          reject(res);
          notify({
            apiName: payload.extraInfo.name,
            apiUrl: payload.extraInfo.url,
            apiAuthor: payload.extraInfo.author,
            url: url,
            data: payload.data,
            message: res.data.msg || res.data.message || "-",
            onRetry: retry,
            onCancel: options.onCancel,
            onClose: () => reject(res),
          });
        } else {
          resolve(res.data.data || res.data);
        }
      })
      .catch((err) => {
        notify({
          apiName: payload.extraInfo.name,
          apiUrl: payload.extraInfo.url,
          apiAuthor: payload.extraInfo.author,
          url: url,
          data: payload.data,
          message: String(err),
          onRetry: retry,
          onCancel: options.onCancel,
          onClose: () => reject(err),
        });
      });
  });
}

function notify(payload: {
  apiName: string;
  apiUrl: string;
  apiAuthor: string;
  url: string;
  data: any;
  message: any;
  onRetry: () => any;
  onClose: () => any;
  onCancel?: () => any;
}) {
  if (process.env.NODE_ENV === "production") return;
  const url = payload.url.replace(corsProxyUrl, "");
  const data = payload.data ? JSON.stringify(payload.data) : "-";
  const id = `notify_${generateUUID()}`;
  const notify = ElNotification.error({
    title: "网络请求出错",
    customClass: id,
    dangerouslyUseHTMLString: true,
    message: `
    <div>
      <div style=" text-align: left;
           word-break: break-all;">
          请求地址：${url}
      </div>
      <div>请求内容：${data}</div>
      <div>出错信息：${payload.message}</div>
    </div>
    `,
    duration: 0,
  });
  setTimeout(() => {
    document
      .querySelector<HTMLDivElement>(`.${id} .el-notification__closeBtn`)
      ?.addEventListener("click", () => payload.onClose(), false);
  }, 600);
  return notify;
}
